#include "widget.h"
#include "readthread.h"
#include <QDebug>
#include <QMouseEvent>
#include <fcntl.h>
#include <unistd.h>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <sys/stat.h>
#include <QImageReader>
#include <QtConcurrent/QtConcurrentRun>
#include <QFutureWatcher>
#include "ui_widget.h" // 包含生成的 UI 头文件

#define FIFO_PATH "/tmp/temp_humidity_fifo"

Widget::Widget(QWidget *parent)
    : QWidget(parent), ui(new Ui::Widget), dir(), ImageCount(0),
      currentImageIndex(0), fifoRetryTimer(new QTimer(this)),
      processTimer(new QTimer(this)), updateTimer(new QTimer(this)),
      m_readThread(nullptr), statusLabel(new QLabel(this)),
      dataQueue(), fifoFile()
{
    ui->setupUi(this);

    // 图像目录路径
    QString imagePath = "/home/elf/work/zhaopian"; // 替换为你的实际图片目录路径

    // 获取目录中的所有图片文件
    dir.setPath(imagePath);
    QStringList filters;
    filters << "*.bmp" << "*.jpg" << "*.jpeg" << "*.png";
    dir.setNameFilters(filters);
    dir.setSorting(QDir::Name); // 按名称排序

    ImageCount = static_cast<uint>(dir.count()); // 获得dir里名字的个数，也表示文件夹下图片的个数

    qDebug() << "Image path:" << imagePath;
    qDebug() << "Images found:" << ImageCount;

    if (ImageCount == 0) {
        qCritical("No images found in directory: %s", imagePath.toStdString().c_str());
        return;
    }

    // 加载第一张图像
    loadImage();

    // 安装事件过滤器
    ui->video->installEventFilter(this);

    this->setWindowFlags(Qt::FramelessWindowHint);

    // 初始化 FIFO 相关组件
    fifoRetryTimer->setInterval(1000); // 1秒重试间隔
    connect(fifoRetryTimer, &QTimer::timeout,
            this, &Widget::tryOpenFIFO);

    processTimer->setInterval(30); // 30ms处理间隔
    connect(processTimer, &QTimer::timeout,
            this, &Widget::processData);

    tryOpenFIFO(); // 首次尝试打开

    // 初始化状态标签
    statusLabel->setAlignment(Qt::AlignCenter);
    statusLabel->move(10, 10);
    updateConnectionStatus(false);

    // 验证组件连接
    qDebug() << "LCD widgets:"
             << ui->lcd_wendu->metaObject()->className()
             << ui->lcd_shidu->metaObject()->className();

    // 强制刷新界面
    QApplication::processEvents();
}

Widget::~Widget()
{
    delete ui;
    fifoFile.close();
    if (m_readThread && m_readThread->isRunning()) {
        m_readThread->requestInterruption();
        m_readThread->wait(1000);
    }
    fifoRetryTimer->stop();
    processTimer->stop();
    delete fifoRetryTimer;
    delete processTimer;
    delete statusLabel;
    delete m_readThread; // 删除 m_readThread
}

bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->video && event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if (mouseEvent->button() == Qt::LeftButton) {
            handleImageClick();
            return true;
        }
    }
    return QObject::eventFilter(obj, event);
}

void Widget::loadImage()
{
    if (ImageCount == 0) {
        qWarning("No images to load.");
        return;
    }
    loadAndDisplayImage(currentImageIndex);
}

void Widget::handleImageClick()
{
    ++currentImageIndex;
    if (currentImageIndex >= ImageCount) {
        currentImageIndex = 0; // 回到第一张图片
    }
    loadAndDisplayImage(currentImageIndex);
}

void Widget::loadAndDisplayImage(uint index)
{
    if (index >= ImageCount) {
        qWarning("Invalid image index: %u", index);
        return;
    }

    // 将 uint 转换为 int 以访问 QStringList
    QString imageName = dir.filePath(dir.entryList()[static_cast<int>(index)]);
    qDebug() << "Loading image:" << imageName;

    QImageReader reader(imageName);
    if (!reader.canRead()) {
        qCritical("Cannot open image file: %s", imageName.toStdString().c_str());
        return;
    }

    // 异步加载图像
    QFuture<QImage> future = QtConcurrent::run([imageName]() -> QImage {
        QImageReader reader(imageName);
        if (!reader.canRead()) {
            qCritical("Cannot read image file asynchronously: %s", imageName.toStdString().c_str());
            return QImage();
        }
        QImage image = reader.read();
        if (image.isNull()) {
            qCritical("Failed to read image file asynchronously: %s", imageName.toStdString().c_str());
        } else {
            qDebug() << "Successfully read image file asynchronously: %s", imageName.toStdString().c_str();
        }
        return image;
    });

    auto watcher = new QFutureWatcher<QImage>();
    connect(watcher, &QFutureWatcher<QImage>::finished, [this, watcher]() {
        QImage image = watcher->result();
        if (image.isNull()) {
            qCritical("Failed to read image file.");
            watcher->deleteLater();
            return;
        }
        QPixmap pixmap = QPixmap::fromImage(image);
        ui->video->setPixmap(pixmap.scaled(ui->video->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
        watcher->deleteLater();
    });
    watcher->setFuture(future);
}

void Widget::tryOpenFIFO()
{
    qDebug() << "尝试打开FIFO，当前FD状态:" << fifoFile.handle();

    if (fifoFile.isOpen()) fifoFile.close();

    // 确保 FIFO 存在
    if (access(FIFO_PATH, F_OK) == -1) {
        qDebug() << "🔄 FIFO 不存在，等待中...";
        fifoRetryTimer->start();
        updateConnectionStatus(false);
        return;
    }

    int fd = ::open(FIFO_PATH, O_RDONLY | O_NONBLOCK);
    if (fd == -1) {
        qDebug() << "🔄 等待 FIFO..." << strerror(errno);
        fifoRetryTimer->start();
        updateConnectionStatus(false);
        return;
    }

    // 使用 QFile 管理原始 fd
    if (!fifoFile.open(fd, QIODevice::ReadOnly | QIODevice::Unbuffered)) {
        qDebug() << "❌ QFile 打开失败:" << fifoFile.errorString();
        ::close(fd);
        fifoRetryTimer->start();
        updateConnectionStatus(false);
        return;
    }

    qDebug() << "✅ FIFO 已连接！原始 FD:" << fd;
    fifoRetryTimer->stop();
    processTimer->start();
    updateTimer->start(1000); // 启动更新定时器，每秒检查一次连接状态
    updateConnectionStatus(true);

    // 创建新的 ReadThread 并传递文件描述符
    if (m_readThread) {
        m_readThread->requestInterruption();
        m_readThread->wait(500);
        delete m_readThread;
    }
    m_readThread = new ReadThread(fd, this);
    connect(m_readThread, &ReadThread::newData, this, &Widget::onNewData);
    connect(m_readThread, &ReadThread::connectionClosed, this, &Widget::tryOpenFIFO); // 连接断开信号
    m_readThread->start();
}

void Widget::updateConnectionStatus(bool connected)
{
    if (!statusLabel) {
        qCritical("statusLabel is not initialized!");
        return;
    }

    QPalette palette;
    palette.setColor(QPalette::WindowText, connected ? Qt::green : Qt::red);
    statusLabel->setPalette(palette);
    statusLabel->setText(connected ? "Connected" : "Disconnected");
}

void Widget::onNewData(QString line)
{
    QMutexLocker locker(&queueMutex);
    if (line.isEmpty()) {
        qWarning() << "收到空数据";
        return;
    }
    dataQueue.enqueue(line);
    qDebug() << "接收数据:" << line;
}

void Widget::processData()
{
    QMutexLocker locker(&queueMutex);
    int maxProcess = 20; // 增加单次处理数量
    QQueue<QString> tempQueue;

    // 优先处理菜式数据
    while (!dataQueue.isEmpty() && maxProcess > 0) {
        QString line = dataQueue.dequeue();
        if (line.startsWith("dish_state:")) {
            parseDataLine(line);
            maxProcess--;
        } else {
            tempQueue.enqueue(line);
        }
    }

    // 处理剩余数据
    while (!tempQueue.isEmpty() && maxProcess-- > 0) {
        parseDataLine(tempQueue.dequeue());
    }

    // 将未处理的数据放回队列前端
    while (!tempQueue.isEmpty()) {
        dataQueue.prepend(tempQueue.dequeue());
    }
}

void Widget::parseDataLine(const QString &line)
{
    static QRegularExpression re_tempHumidity("^\\s*([+-]?\\d*\\.?\\d+)\\s+([+-]?\\d*\\.?\\d+)\\s*$");
    static QRegularExpression re_dishState("^dish_state:([^;]+);(.+)$"); // 新增组合匹配

    // 匹配组合消息（菜式 + 状态）
    QRegularExpressionMatch matchDishState = re_dishState.match(line);
    if (matchDishState.hasMatch()) {
        QString dish = matchDishState.captured(1).trimmed();
        QString state = matchDishState.captured(2).trimmed();
        QMetaObject::invokeMethod(this, [=](){
            setDishRecommendation(dish);
            setFoodState(state); // 同步更新
        }, Qt::QueuedConnection);
        return;
    }

    // 匹配温湿度数据
    QRegularExpressionMatch matchTempHumidity = re_tempHumidity.match(line);
    if (matchTempHumidity.hasMatch()) {
        bool ok1, ok2;
        double temp = matchTempHumidity.captured(1).toDouble(&ok1);
        double humi = matchTempHumidity.captured(2).toDouble(&ok2);

        if (ok1 && ok2) {
            QMetaObject::invokeMethod(this, [=](){
                ui->lcd_wendu->display(temp);
                ui->lcd_shidu->display(humi);
                qDebug() << "🔄 更新显示:" << temp << humi;
            }, Qt::QueuedConnection);
        } else {
            qWarning() << "转换失败:" << line;
        }
        return;
    }

    qWarning() << "无效数据格式:" << line;
}

void Widget::setDishRecommendation(const QString &dish)
{
    ui->dishes->setText(dish);
    qDebug() << "🔄 更新推荐菜品:" << dish;
}

void Widget::setFoodState(const QString &state)
{
    ui->food_state->setText(state);
    qDebug() << "🔄 更新食物状态:" << state;
}



